package cn.fsd.service.impl;

import cn.fsd.domain.*;
import cn.fsd.exception.StoreroomException;
import cn.fsd.exception.StoreroomExceptionCodeMsg;
import cn.fsd.mapper.Storeroom_commodityMapper;
import cn.fsd.mapper.TempMapper;
import cn.fsd.nacos.CustomerServer;
import cn.fsd.nacos.DeliveryServer;
import cn.fsd.nacos.DispatchServer;
import cn.fsd.service.StockInOutService;
import cn.fsd.util.RedisKey;
import cn.fsd.util.StoreroomRedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class StockInOutServiceImpl implements StockInOutService {

    final Storeroom_commodityMapper storeroom_commodityMapper;
    final StoreroomRedisUtils redisUtil;

    @Autowired
    TempMapper tempMapper;
    final DeliveryServer deliveryServer;

    @Autowired
    DispatchServer dispatchServer;

    @Autowired
    CustomerServer customerServer;

    @Autowired
    public StockInOutServiceImpl(Storeroom_commodityMapper storeroom_commodityMapper, StoreroomRedisUtils redisUtil, DeliveryServer deliveryServer) {
        this.storeroom_commodityMapper = storeroom_commodityMapper;
        this.redisUtil = redisUtil;
        this.deliveryServer = deliveryServer;
    }

    /**
     * 购货入库的货物到货时，选择购货单进行购货入库操作,之后自动进行异步的货物分配操作，将订单挂起
     */
    @Override
    public void purchaseIn(String bill_id) {
        Purchase_bill purchase_bill = deliveryServer.getPurchase_billById(bill_id);
        //获得实际入库数量(减去退货部分)
        Integer purchaseInNum = purchase_bill.getPurchase_num() - purchase_bill.getReturn_num();
        String commodity_id = purchase_bill.getCommodity_id();
        String storeroom_id = purchase_bill.getStoreroom_id();
        Storeroom_commodity record = storeroom_commodityMapper.selectByPrimaryKey(commodity_id, storeroom_id);

        //添加到可分配
        record.setTransferable_num(record.getTransferable_num() + purchaseInNum);
        //从预计到达减去
        record.setScheduled_num(record.getScheduled_num() - purchaseInNum);
        //从缺货量中减去
        record.setOut_of_stock(Math.max(record.getOut_of_stock() - purchaseInNum, 0));

        purchase_bill.setPurchase_status(1);
        //远程调用分站服务，修改购货入库单状态为已入库
        deliveryServer.changePurchase_status(purchase_bill);
        storeroom_commodityMapper.updateByPrimaryKey(record);
        autoHandleStockOutOrder(storeroom_id, commodity_id);
    }

    /**
     * 按照缺货订单队列，自动处理某仓库某件货物的订单
     * 如果遇到已撤销订单，跳过该订单，并从set中删除
     */
    private void autoHandleStockOutOrder(String storeroom_id, String commodity_id) {
        Storeroom_commodity record = storeroom_commodityMapper.selectByPrimaryKey(commodity_id, storeroom_id);
        String stockOutKey = getQueueKey(storeroom_id, commodity_id);
        String cancelKey = RedisKey.getCanceledOrderSetKey();
        while (true) {
            if (redisUtil.listLength(stockOutKey) == 0) break;
            String order_id = (String) redisUtil.queueTop(stockOutKey);
            if (redisUtil.isMember(cancelKey, order_id)) {
                redisUtil.remove(cancelKey, order_id);
                redisUtil.queueOut(stockOutKey);
                continue;
            }
            Order order = customerServer.getTheOrder(order_id);

            if (order.getCommodity_num() <= record.getTransferable_num()) {
                record.setTransferable_num(record.getTransferable_num() - order.getCommodity_num());
                record.setTransferred_num(record.getTransferred_num() + order.getCommodity_num());
                customerServer.changeOrderStatus(order_id, "已挂起");
                customerServer.changeDeliveryStatus(order_id, "正常");
                storeroom_commodityMapper.updateByPrimaryKey(record);
                redisUtil.queueOut(stockOutKey);
            } else {
                break;
            }
        }
    }

    @Override
    public void transferOut(String transfer_id) {
        Transfer transfer = dispatchServer.findById(transfer_id);
        Storeroom_commodity storeroom_commodity =
                storeroom_commodityMapper.selectByPrimaryKey(transfer.getCommodity_id(), transfer.getStoreroom_id());
        storeroom_commodity.setTransferred_num(storeroom_commodity.getTransferred_num() - transfer.getTransfer_sum());
        transfer.setTransfer_status("已出库");
        dispatchServer.changeStatus(transfer);
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(transfer.getOrder_id(), "中心库房出库");
    }

    @Override
    public void transferIn(String transfer_id) throws StoreroomException {
        Transfer transfer = dispatchServer.findById(transfer_id);
        Storeroom_commodity storeroom_commodity = storeroom_commodityMapper.selectByPrimaryKey(transfer.getCommodity_id(), transfer.getStation_id());
        int blank = storeroom_commodity.getMax_num() - storeroom_commodity.getScheduled_num() - storeroom_commodity.getExpected_exchange() - storeroom_commodity.getTransferred_num() - storeroom_commodity.getExchanged_num();
        if (blank < transfer.getTransfer_sum()) {
            throw new StoreroomException(StoreroomExceptionCodeMsg.STOREROOM_FULL_TRANSFER_IN);
        }
        storeroom_commodity.setTransferred_num(storeroom_commodity.getTransferred_num() + transfer.getTransfer_sum());
        transfer.setTransfer_status("已送达");
        dispatchServer.changeStatus(transfer);
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(transfer.getOrder_id(), "配送站到货");

        Task task = tempMapper.findTaskByOrderId(transfer.getOrder_id());
        task.setTask_status("可分配");
        tempMapper.updateTask(task);
    }

    @Override
    public void deliveryOut(String task_id) {
        Task task = tempMapper.findTaskById(task_id);
        //获取任务单关联的订单（即换货退货的新订单）
        Order order = customerServer.getTheOrder(task.getOrder_id());
        Storeroom_commodity storeroom_commodity =
                storeroom_commodityMapper.selectByPrimaryKey(order.getCommodity_id(), task.getStation_id());
        storeroom_commodity.setTransferred_num(storeroom_commodity.getTransferred_num() - task.getCount_inTask());
        task.setTask_status("已领货");
        tempMapper.updateTask(task);
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(task.getOrder_id(), "已领货");
    }

    @Override
    public void exchangeCheckIn(String task_id) {
        // TODO: 2023/7/16
        Task task = tempMapper.findTaskById(task_id);
        //获取任务单关联的订单（即换货退货的新订单）
        Order order = customerServer.getTheOrder(task.getOrder_id());
        Storeroom_commodity storeroom_commodity =
                storeroom_commodityMapper.selectByPrimaryKey(order.getCommodity_id(), task.getStation_id());

        //获得分站仓库的可用库存量
        int blank = storeroom_commodity.getMax_num() - storeroom_commodity.getScheduled_num()
                - storeroom_commodity.getExpected_exchange() - storeroom_commodity.getTransferred_num()
                - storeroom_commodity.getExchanged_num();
        if (blank < task.getCount_inTask()) {
            throw new StoreroomException(StoreroomExceptionCodeMsg.STOREROOM_FULL_EXCHANGE_CHECKIN);
        }
        storeroom_commodity.setExchanged_num(storeroom_commodity.getExchanged_num() + task.getCount_inTask());

        task.setTask_status("已完成");
        tempMapper.updateTask(task);
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(task.getOrder_id(), "分站库房退货入库");
    }

    @Override
    public void exchangeOut(String task_id) {
        Task task = tempMapper.findTaskById(task_id);
        //获取任务单关联的订单（即换货退货的新订单）
        Order order = customerServer.getTheOrder(task.getOrder_id());
        Storeroom_commodity storeroom_commodity = storeroom_commodityMapper.selectByPrimaryKey(order.getCommodity_id(), task.getStation_id());
        storeroom_commodity.setExchanged_num(storeroom_commodity.getExchanged_num() - task.getCount_inTask());
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(task.getOrder_id(), "分站库房退货出库");
    }

    @Override
    public void exchangeIn(String task_id) {
        Task task = tempMapper.findTaskById(task_id);
        //获取任务单关联的订单（即换货退货的新订单）
        Order order = customerServer.getTheOrder(task.getOrder_id());
        Storeroom_commodity storeroom_commodity = storeroom_commodityMapper.selectByPrimaryKey(order.getCommodity_id(), tempMapper.getOldStoreroom(task.getTask_id()));

        //获得中心仓库的可用库存量
        int blank = storeroom_commodity.getMax_num() - storeroom_commodity.getScheduled_num() - storeroom_commodity.getExpected_exchange() - storeroom_commodity.getTransferred_num() - storeroom_commodity.getExchanged_num();
        if (blank < task.getCount_inTask()) {
            throw new StoreroomException(StoreroomExceptionCodeMsg.STOREROOM_FULL_EXCHANGE_IN);
        }
        storeroom_commodity.setExchanged_num(storeroom_commodity.getExchanged_num() + task.getCount_inTask());

        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(task.getOrder_id(), "中心库房退货入库");
    }

    @Override
    public void centerOut(String task_id) {
        Task task = tempMapper.findTaskById(task_id);
        //获取任务单关联的订单（即换货退货的新订单）
        Order order = customerServer.getTheOrder(task.getOrder_id());
        Storeroom_commodity storeroom_commodity = storeroom_commodityMapper.selectByPrimaryKey(order.getCommodity_id(), tempMapper.getOldStoreroom(task.getTask_id()));
        storeroom_commodity.setExchanged_num(storeroom_commodity.getExchanged_num() - task.getCount_inTask());
        storeroom_commodityMapper.updateByPrimaryKey(storeroom_commodity);
        customerServer.changeOrderStatus(task.getOrder_id(), "中心站退货");
    }


    private String getQueueKey(String storeroom_id, String commodity_id) {
        return RedisKey.getStockOutOrderQueueKey(storeroom_id, commodity_id);
    }
}
